Skip to content

[#329] Index MCV2_Bond mint/burn trades for storyline tokens#334

Merged
realproject7 merged 2 commits intomainfrom
task/329-trade-indexer
Mar 18, 2026
Merged

[#329] Index MCV2_Bond mint/burn trades for storyline tokens#334
realproject7 merged 2 commits intomainfrom
task/329-trade-indexer

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Migration: trade_history table with (tx_hash, log_index) unique constraint + indexes
  • Cron route (/api/cron/trade-history): Scans MCV2_Bond Minted/Burned events for known storyline tokens only; own cursor (id=2); CRON_SECRET fail-closed in production
  • Direct indexer (/api/index/trade): Accepts txHash + tokenAddress, decodes events, upserts immediately
  • TradingWidget: Fire-and-forget POST to trade indexer after successful mint/burn
  • ABI: Added Minted/Burned event definitions from MCV2_Bond.sol
  • Types: Added trade_history to Database interface

Price per token computed as reserveAmount / tokenAmount. Total supply read at trade block number.

Fixes #329

Test plan

- Migration: trade_history table with (tx_hash, log_index) uniqueness
- Database types: added trade_history to Database interface
- ABI: added Minted/Burned event definitions from MCV2_Bond.sol
- Cron route: /api/cron/trade-history scans MCV2_Bond events for
  known storyline tokens only, with own cursor (id=2) and
  CRON_SECRET fail-closed auth
- Direct indexer: /api/index/trade accepts txHash+tokenAddress,
  decodes mint/burn events and upserts to trade_history
- TradingWidget: fire-and-forget POST to trade indexer after
  successful mint/burn for instant chart updates
- Price per token computed as reserveAmount/tokenAmount
- Total supply read at trade block number

Fixes #329

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The trade-history shape is reasonable, but the cron cursor design is currently incompatible with the existing schema. As written, the new cron route cannot persist or advance its own cursor.

Findings

  • [high] trade-history cron uses backfill_cursor.id = 2, but the existing table schema explicitly enforces check (id = 1).
    • File: src/app/api/cron/trade-history/route.ts:11
    • Suggestion: Either migrate backfill_cursor to support multiple ids, or create a separate cursor table for trade history. Right now insert({ id: 2, ... }) at src/app/api/cron/trade-history/route.ts:47 and later update(...).eq("id", 2) can never succeed against supabase/migrations/00003_backfill_cursor.sql, so the cron route will rescan from block 0 on every run and never maintain state.

Decision

Request changes. The cron data layer is not functional until its cursor storage can actually persist id = 2.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

T2b APPROVE

Verified against acceptance criteria and contract source:

Migration: trade_history with unique (tx_hash, log_index) idempotency, numeric types for price precision, indexes on (token_address, block_timestamp) and storyline_id

Cron: Own cursor (ID=2), verifyCron fails closed in production, loads known storyline tokens from DB and skips unknown events, block timestamp caching ✅

ABI: Minted/Burned event signatures match MCV2_Bond.sol upstream — indexed token+account, non-indexed tokenAmount+reserveAmount/refundAmount+beneficiary

Price: reserveAmount / tokenAmount (both 18 decimals for WETH/PLOT reserve) with correct field per event type (reserveAmount for Minted, refundAmount for Burned) ✅

Direct indexer: Upserts with conflict handling, storyline lookup by token_address, no auth needed (write-only fire-and-forget) ✅

TradingWidget: Fire-and-forget POST after successful mint/burn, .catch(() => {}) suppresses errors ✅

Non-blocking note: cron errors increment errors count but cursor still advances past failed blocks (same pattern as original backfill before #322). Consider logging to backfill_failures for consistency if trade indexing reliability matters.

Drop check(id=1) constraint on backfill_cursor so the trade-history
cron can use its own cursor row (id=2). Seeds the new row.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The follow-up fixes the cursor-schema incompatibility by migrating backfill_cursor to support multiple ids and seeding the trade-history cursor row. The trade-history data layer now matches issue #329’s intended design.

Findings

  • [low] The prior blocker is resolved: backfill_cursor no longer enforces id = 1, and the migration seeds id = 2 for the trade-history cron.
    • File: supabase/migrations/00017_backfill_cursor_multi.sql:1
    • Suggestion: None.

Decision

Approve. The cron cursor can now persist independently, the direct indexer and migration stay within scope, and local npm run build plus npm run typecheck both pass.

@realproject7 realproject7 merged commit 75bd6af into main Mar 18, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Index MCV2_Bond mint/burn trades for storyline tokens

2 participants